#pragma once
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <stdarg.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


#define Info    0
#define Debug   1
#define Warning 2
#define Error   3
#define Fatal   4
#define SIZE 1024
#define screen    0
#define onefile   1
#define classfile 2
#define file "log.txt"
// #define printMethod classfile
// #define path "./Log/"

class Log
{
public:
    Log()
    {
        path = "./Log/";
        printMethod = screen;
    }

    ~Log()
    {}

    void enable(int method)
    {
        printMethod = method;
    }

    void operator()(int level, const char* format, ...)
    {
         time_t t = time(nullptr);
        struct tm* ctime = localtime(&t);
        // printf("%d-%d-%d %d-%d-%d\n", ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
        // ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        std::string levels = levelToString(level);
        char leftbuffer[SIZE] = {0};
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d-%d-%d]", levels.c_str(), 
        ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        //将可变参数提取出来
        char rightbuffer[SIZE] = {0};
        va_list s;
        va_start(s, format);
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        //将所有字符串拼接起来
        char logtxt[SIZE*2] = {0};
        snprintf(logtxt, sizeof(logtxt), "%s%s\n", leftbuffer, rightbuffer);

        //先打印出来测试一下
        // std::cout << logtxt << std::endl;
        
        //不同的打印方式
        printLog(level, logtxt);
    }

    std::string levelToString(int level)
    {
        switch(level)
        {
            case(Info):
                return "Info";
            case(Debug):
                return "Debug";
            case(Warning):
                return "Warning";
            case(Error):
                return "Error";
            case(Fatal):
                return "Fatal";
        }
    }

    void printOneFile(const char* filename, const char* logtxt)
    {
        int fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0666);
        if(fd == -1)  return;
        write(fd, logtxt, strlen(logtxt));
        close(fd);
    }

    void printClassFile(int level, const char* logtxt)
    {
        std::string filename = path + levelToString(level) + "." + "txt";
        std::cout << filename << std::endl;
        printOneFile(filename.c_str(), logtxt); 
    }

    void printLog(int level, const char* logtxt)
    {
        switch(printMethod)
        {
            case(screen):
                std::cout << logtxt << std::endl; 
                break;
            case(onefile):
                printOneFile("log.txt", logtxt);
                break;
            case(classfile):
                printClassFile(level, logtxt);
                break;
        }
    }

    // void logmessage(int level, const char* format, ...)
    // {
    //     time_t t = time(nullptr);
    //     struct tm* ctime = localtime(&t);
    //     // printf("%d-%d-%d %d-%d-%d\n", ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
    //     // ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    //     std::string levels = levelToString(level);
    //     char leftbuffer[SIZE] = {0};
    //     snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d-%d-%d]", levels.c_str(), 
    //     ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    //     //将可变参数提取出来
    //     char rightbuffer[SIZE] = {0};
    //     va_list s;
    //     va_start(s, format);
    //     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    //     va_end(s);

    //     //将所有字符串拼接起来
    //     char logtxt[SIZE*2] = {0};
    //     snprintf(logtxt, sizeof(logtxt), "%s%s\n", leftbuffer, rightbuffer);

    //     //先打印出来测试一下
    //     // std::cout << logtxt << std::endl;
        
    //     //不同的打印方式
    //     printLog(level, logtxt);
    // }
private:
    std::string path;
    int printMethod;
};